 1.SQL优化
   
   列裁剪和分区裁剪
   列裁剪是在查询时只读取需要的列；分区裁剪就是只读取需要的分区。
   简单的说：select 中不要有多余的列，坚决避免 select * from tab;
   查询分区表，不读多余的数据；
   select uid, event_type, record_data
from calendar_record_log
where pt_date >= 20190201 and pt_date <= 20190224
and status = 0;
 
 2.sort by 代替 order by
   
   HiveQL中的order by与其他关系数据库SQL中的功能一样，是将结果按某字段全局
排序，这会导致所有map端数据都进入一个reducer中，在数据量大时可能会长时间
计算不完。
  如果使用sort by，那么还是会视情况启动多个reducer进行排序，并且保证每个
reducer内局部有序。为了控制map端数据分配到reducer的key，往往还要配合
distribute by 一同使用。如果不加 distribute by 的话，map端数据就会随机分配到
reducer。

 3.group by 代替 count(distinct)
   
   当要统计某一列的去重数时，如果数据量很大，count(distinct) 会非常慢。原因与
order by类似，count(distinct)逻辑只会有很少的reducer来处理。此时可以用
group by 来改写：
   -- 原始SQL
   select count(distinct uid) from tab;
   -- 优化后的SQL
select count(1)
from (select uid
from tab
group by uid) tmp;
   这样写会启动两个MR job（单纯distinct只会启动一个），所以要确保数据量大到启
动job的overhead远小于计算耗时，才考虑这种方法。当数据集很小或者key的倾斜
比较明显时，group by还可能会比distinct慢。
 
 4.group by 配置调整
   
   map端预聚合
   group by时，如果先起一个combiner在map端做部分预聚合，可以有效减少shuffle
数据量。
   -- 默认为true
   set hive.map.aggr = true
   Map端进行聚合操作的条目数
   set hive.groupby.mapaggr.checkinterval = 100000 
   通过 hive.groupby.mapaggr.checkinterval 参数也可以设置map端预聚合的行数
阈值，超过该值就会分拆job，默认值10W。
   倾斜均衡配置项
   group by时如果某些key对应的数据量过大，就会发生数据倾斜。Hive自带了一个均
衡数据倾斜的配置项 hive.groupby.skewindata ，默认值false。
   其实现方法是在group by时启动两个MR job。第一个job会将map端数据随机输入reducer
，每个reducer做部分聚合，相同的key就会分布在不同的reducer中。第二个job再将前面
预处理过的数据按key聚合并输出结果，这样就起到了均衡的效果。
  但是，配置项毕竟是死的，单纯靠它有时不能根本上解决问题，建议了解数据倾斜的
细节，并优化查询语句。